/**
 * Copyright 厦门中软海晟信息技术有限公司 版权所有 违者必究 2019
 */
package com.opencvjava.lessons.imgproc;

import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Size;
import org.springframework.stereotype.Service;

import static com.opencvjava.support.util.CvUtils.imshow;
import static com.opencvjava.support.util.CvUtils.mat;
import static org.opencv.imgproc.Imgproc.*;
import static org.opencv.imgcodecs.Imgcodecs.*;
import static org.opencv.core.Core.*;
/**
 * @author : sunzb(sunzb@hsit.com.cn)
 * @date: 2019/1/4
 */
@Service
public class L5_MoreMorphology {
    private int kernelSize = 2;
    public void test() {
        Mat src, dst = new Mat();
        Mat element = getStructuringElement(CV_SHAPE_RECT,
                new Size(2 * kernelSize + 1, 2 * kernelSize + 1),
                new Point(kernelSize, kernelSize));
        // Opening 开操作 先腐蚀后膨胀 erode -> dilate
        // open(src,element)=dilate(erode(src,element))
        // 先腐蚀会把小有的干掉（大无吃掉小有，放大了大无），再膨胀的目的是还原大有的边缘
        // 结果是平滑了对象的轮廓，断开了狭窄的连接，去掉了细小的突出部分
        src = mat("morphology","opening.png");
        imshow("opening src", src);
        morphologyEx(src, dst, MORPH_OPEN, element);
        imshow("opening dst", dst);
        // Closing 闭操作 先膨胀后腐蚀 dilate -> erode
        // close(src,element)=erode(dilate(src,element))
        // 先膨胀把小无的干掉（大有吃掉小无，放大了大有），再腐蚀的目的是还原大无的边缘
        // 结果是平滑了对象的轮廓，一般会将狭窄的缺口连接起来形成细长的弯口，并填充比结构元素小的洞
        src = mat("morphology", "closing.png");
        imshow("closing src", src);
        morphologyEx(src, dst, MORPH_CLOSE, element);
        imshow("closing dst", dst);
        // Morphological Gradient 形态学梯度 膨胀一次的图片减去腐蚀一次的图片
        // 如果是黑白二值图，那就相当于结果是一条白色边缘
        // morphgrad(src,element)=dilate(src,element)−erode(src,element)
        kernelSize = 1;
        element = getStructuringElement(CV_SHAPE_RECT,
                new Size(2 * kernelSize + 1, 2 * kernelSize + 1),
                new Point(kernelSize, kernelSize));
        src = mat("morphology", "gradient.png");
        imshow("gradient src", src);
        morphologyEx(src, dst, MORPH_GRADIENT, element);
        imshow("gradient dst", dst);
        // Top Hat 顶帽操作
        // tophat(src,element)=src−open(src,element)
        // 开操作去掉的部分其实就是 顶帽的这个差值，用来突出
        kernelSize = 4;
        element = getStructuringElement(CV_SHAPE_RECT,
                new Size(2 * kernelSize + 1, 2 * kernelSize + 1),
                new Point(kernelSize, kernelSize));
        src = mat("morphology", "top_hat.png");
        imshow("top_hat src", src);
        morphologyEx(src, dst, MORPH_OPEN, element);
        imshow("用来和top_hat比较的开操作", dst);
        morphologyEx(src, dst, MORPH_TOPHAT, element);
        imshow("top_hat dst", dst);
        // Black Hat 黑帽操作
        // blackhat(src,element)=close(src,element)−src
        src = mat("morphology", "black_hat.png");
        imshow("black_hat src", src);
        morphologyEx(src, dst, MORPH_CLOSE, element);
        imshow("用来和black_hat比较的闭操作", dst);
        morphologyEx(src, dst, MORPH_BLACKHAT, element);
        imshow("black_hat dst", dst);
    }
}
